package com.ahua.mallchat.common.service.impl;

import cn.hutool.core.thread.NamedThreadFactory;
import cn.hutool.http.HttpUtil;
import com.ahua.mallchat.common.dao.UserDao;
import com.ahua.mallchat.common.domain.pojo.IpDetail;
import com.ahua.mallchat.common.domain.pojo.IpInfo;
import com.ahua.mallchat.common.domain.pojo.User;
import com.ahua.mallchat.common.domain.vo.ApiResult;
import com.ahua.mallchat.common.service.IpService;
import com.ahua.mallchat.common.utils.JsonUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class IpServiceImpl implements IpService {
    @Resource
    private UserDao userDao;

    /**
     * 淘宝解析ip地址的api
     * 填充:ip
     */
    public static final String TAOBAO_API_URL = "https://ip.taobao.com/outGetIpInfo?ip=%s&accessKey=alibaba-inc";

    /**
     * 创建线程池
     * 关键参数：
     * 1.核心线程数为1
     * 2.最大线程数为1
     */
    private static ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(500),
            new NamedThreadFactory("refresh-ipDetail", false));

    @Override
    public void refreshUserIpDetailAsync(Long uid) {
        executor.execute(() -> {
            User user = userDao.getById(uid);
            IpInfo ipInfo = user.getIpInfo();
            if (Objects.isNull(ipInfo)) {
                return;
            }
            boolean needRefreshIp = ipInfo.needRefreshIp();
            if (!needRefreshIp) {
                //ip没变化的话,就不用刷新
                return;
            }
            //现在就是处理流程了
            String ip = ipInfo.getUpdateIp();
            IpDetail ipDetail = tryGetIpDetailOrNullThreeTimes(ip);
            if (Objects.nonNull(ipDetail)) {
                ipInfo.refreshIpDetail(ipDetail);
                User update = new User();
                update.setId(user.getId());
                update.setIpInfo(ipInfo);
                userDao.updateById(update);
            }
        });
    }

    /**
     * 尝试获取ip解析的详情 最大重试次数3
     *
     * @param ip
     * @return
     */
    private IpDetail tryGetIpDetailOrNullThreeTimes(String ip) {
        for (int i = 0; i < 3; i++) {
            IpDetail ipDetail = getIpDetailOrNull(ip);
            if (Objects.nonNull(ipDetail)) {
                return ipDetail;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                log.error("tryGetIpDetailOrNullThreeTimes InterruptedException", e);
            }
        }
        return null;
    }

    private IpDetail getIpDetailOrNull(String ip) {
        try {
            String url = String.format(TAOBAO_API_URL, ip);
            String apiResult = HttpUtil.get(url);
            if (!StringUtils.hasText(apiResult)) {
                return null;
            }

            ApiResult<IpDetail> ipDetailApiResult = JsonUtils.toObj(apiResult, new TypeReference<ApiResult<IpDetail>>() {
            });
            return ipDetailApiResult.getData();
        } catch (Exception e) {
            return null;
        }
    }
}
